package com.bayss.core.service.station;



import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.bayss.core.DokoServerException;
import com.bayss.core.DokoServerExceptionFactor;
import com.bayss.core.entity.address.AddressFixedInfo;
import com.bayss.core.entity.station.Station;
import com.bayss.core.entity.station.StationExample;
import com.bayss.core.entity.station.mapper.StationMapper;
import com.bayss.core.entity.user.AddressInfo;
import com.bayss.core.service.address.AddressService;
import com.bayss.core.util.FileUtil;
import com.bayss.core.util.OrderUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Slf4j
@Service
public class StationService {

    private final AddressService addressService;

    private final StationMapper stationMapper;

    private final static String INDEX_RANGE = "index_range";

    private final static String ADD_RANGE = "add_range";

    private final static String INDEX_TIME = "index_time";

    private final static String ADD_TIME = "add_time";

    private final static String START = "start";

    private final static String END = "end";

    private final static String PRICE = "price";


    @Autowired
    public StationService(AddressService addressService, StationMapper stationMapper) {
        this.addressService = addressService;
        this.stationMapper = stationMapper;
    }

    public boolean save(Station station){
        station.setStatus(1);
        station.setStationPic(FileUtil.formatImgUrl(station.getStationPic()));
        return stationMapper.insertSelective(station) > 0;
    }

    public boolean update(Station station){
        Long stationId = station.getId();
        Station oldStation = stationMapper.selectByPrimaryKey(stationId);

        String latitude = station.getLatitude();
        String longitude = station.getLongitude();
        String stationAddr = station.getStationAddr();
        if (StringUtils.isNotBlank(latitude) && StringUtils.isNotBlank(longitude)) {
            oldStation.setLatitude(latitude);
            oldStation.setLongitude(longitude);
            oldStation.setStationAddr(stationAddr);
        }

        String stationMaster = station.getStationMaster();
        String stationName = station.getStationName();
        String stationPhone = station.getStationCelliphone();
        String openStartTime = station.getOpenStartTime();
        String openEndTime = station.getOpenEndTime();
        Integer doTime = station.getDoTime();
        Integer recvTime = station.getRecvTime();
        Integer deliveryRange = station.getDeliveryRange();
        String orderEndTime = station.getOrderEndTime();
        String stationPic = FileUtil.formatImgUrl(station.getStationPic());
        String sendPriceRule = station.getSendPriceRule();
        String sendTimeRule = station.getSendTimeRule();
        if (StringUtils.isNotBlank(stationMaster)) {
            oldStation.setStationMaster(stationMaster);
        }
        if (StringUtils.isNotBlank(stationName)) {
            oldStation.setStationName(stationName);
        }
        if (StringUtils.isNotBlank(stationPhone)) {
            oldStation.setStationCelliphone(stationPhone);
        }
        if (StringUtils.isNotBlank(openStartTime)) {
            oldStation.setOpenStartTime(openStartTime);
        }
        if (StringUtils.isNotBlank(openEndTime)) {
            oldStation.setOpenEndTime(openEndTime);
        }
        if (doTime != null) {
            oldStation.setDoTime(doTime);
        }
        if (recvTime != null) {
            oldStation.setRecvTime(recvTime);
        }
        if (deliveryRange != null) {
            oldStation.setDeliveryRange(deliveryRange);
        }
        if (StringUtils.isNotBlank(orderEndTime)) {
            oldStation.setOrderEndTime(orderEndTime);
        }
        if (StringUtils.isNotBlank(stationPic)) {
            oldStation.setStationPic(stationPic);
        }
        if (StringUtils.isNotBlank(sendTimeRule)) {
            JSONObject jsonObject = JSONObject.parseObject(sendTimeRule);
            jsonObject.put(INDEX_RANGE, jsonObject.getIntValue(INDEX_RANGE)*1000);
            jsonObject.put(ADD_RANGE, jsonObject.getIntValue(ADD_RANGE)*1000);
            oldStation.setSendTimeRule(jsonObject.toJSONString());
        }
        if (StringUtils.isNotBlank(sendPriceRule)) {
            oldStation.setSendPriceRule(sendPriceRule);
        }
        return stationMapper.updateByPrimaryKey(oldStation) > 0;
    }

    public boolean del(Long id){
        return stationMapper.deleteByPrimaryKey(id) > 0;
    }


    public List<Station> getByWeb(Long addrId, Integer isExistAddr, String longitude, String latitude){
        List<Station> stations = get();
        if (isExistAddr == 1) {
            AddressInfo addressInfo = addressService.get(addrId);
            if (addressInfo.getFixAddrId() > 0) {
                AddressFixedInfo addressFixedInfo = addressInfo.getAddressFixedInfo();
                if (addressFixedInfo != null) {
                    for (Station station : stations) {
                        if (station.getId().longValue() == addressFixedInfo.getStationId()) {
                            station.setUsable(1);
                        } else {
                            station.setUsable(0);
                        }
                    }
                } else {
                    throw new DokoServerException(DokoServerExceptionFactor.PARAM_VERIFY_FAIL, "固定地址已经被移除   ");
                }
            } else {
                for (Station station : stations) {
                    double m = addressService.costM(addrId, station.getId());
                    if (station.getDeliveryRange() > m) {
                        station.setUsable(1);
                    } else {
                        station.setUsable(0);
                    }
                }
            }
        } else {
            for (Station station : stations) {
                double s = OrderUtils.costM(Double.parseDouble(latitude),
                        Double.parseDouble(longitude),
                        Double.parseDouble(station.getLatitude()),
                        Double.parseDouble(station.getLongitude()));
                if (station.getDeliveryRange() > s) {
                    station.setUsable(1);
                } else {
                    station.setUsable(0);
                }
            }
        }
        return stations;
    }


    public List<Station> get(){
        StationExample stationExample = new StationExample();
        stationExample.createCriteria().andIdIsNotNull();
        return stationMapper.selectByExample(stationExample);
    }

    public boolean enable(Long id){
        Station station = stationMapper.selectByPrimaryKey(id);
        station.setStatus(0);
        return stationMapper.updateByPrimaryKey(station) > 0;
    }

    public boolean resume(Long id){
        Station station = stationMapper.selectByPrimaryKey(id);
        station.setStatus(1);
        return stationMapper.updateByPrimaryKey(station) > 0;
    }

    public Station get(Long stationId){
        return stationMapper.selectByPrimaryKey(stationId);
    }

    public boolean isOpen(Long stationId){
        String day = LocalDate.now().toString();
        Station station = stationMapper.selectByPrimaryKey(stationId);
        String start = day+" "+station.getOpenStartTime();
        String end = day+" "+station.getOpenEndTime();
        DateTimeFormatter df = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
        LocalDateTime startParse = LocalDateTime.parse(start, df);
        LocalDateTime endParse = LocalDateTime.parse(end, df);
        long s = LocalDateTime.from(startParse).atZone(ZoneId.systemDefault()).toInstant().toEpochMilli();
        long e = LocalDateTime.from(endParse).atZone(ZoneId.systemDefault()).toInstant().toEpochMilli();
        return s < System.currentTimeMillis() && e > System.currentTimeMillis();
    }

    public Map<String, Long> costTime(Long addressId, Long stationId){
        Station station = stationMapper.selectByPrimaryKey(stationId);
        String sendTimeRule = station.getSendTimeRule();
        if (StringUtils.isBlank(sendTimeRule)) {
            throw new DokoServerException(DokoServerExceptionFactor.PARAM_VERIFY_FAIL, "配送站配置问题，请联系客服~");
        }

        JSONObject ruleObj = JSONObject.parseObject(sendTimeRule);
        long indexRange = 0;
        long addRange = 0;
        long indexTime = 0;
        long addTime = 0;
        if (ruleObj != null) {
            indexRange = ruleObj.getLongValue(INDEX_RANGE);
            addRange = ruleObj.getLongValue(ADD_RANGE);
            indexTime = ruleObj.getLongValue(INDEX_TIME);
            addTime = ruleObj.getLongValue(ADD_TIME);
        }

        long sumTime = indexTime + station.getDoTime() + station.getRecvTime();

        Map<String, Long> map = new HashMap<>();
        map.put("do_time", indexTime + station.getDoTime());
        map.put("sum_time", sumTime);

        if (addressId != 0) {
            double range = addressService.costM(addressId, stationId);
            if (range > indexRange) {
                double s = range - indexRange;
                int i = BigDecimal.valueOf(s).divide(BigDecimal.valueOf(addRange)).setScale(0, BigDecimal.ROUND_UP).intValue();
                long res = sumTime + i * addTime;
                map.put("sum_time", res);
            }
        }
        return map;
    }

    public int costPrice(Long addressId, Long stationId){
        Station station = stationMapper.selectByPrimaryKey(stationId);
        String sendPriceRule = station.getSendPriceRule();
        if (StringUtils.isBlank(sendPriceRule)) {
            throw new DokoServerException(DokoServerExceptionFactor.PARAM_VERIFY_FAIL, "配送站配置问题，请联系客服~");
        }

        JSONArray ruleArray = JSONObject.parseArray(sendPriceRule);
        double range = addressService.costM(addressId, stationId);
        for (int i=0; i<ruleArray.size(); i++) {
            JSONObject obj = ruleArray.getJSONObject(i);
            double start = obj.getDouble(START);
            double end = obj.getDouble(END);
            if (Double.doubleToLongBits(range) > Double.doubleToLongBits(start)
                    && Double.doubleToLongBits(range) < Double.doubleToLongBits(end)) {
                return obj.getIntValue(PRICE);
            }
        }
        return 10;
    }
}
